package zy.service.money.access.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import zy.dao.approve.ApproveRecordDAO;
import zy.dao.money.access.AccessDAO;
import zy.dao.money.bank.BankDAO;
import zy.dao.money.bank.BankRunDAO;
import zy.dao.sys.print.PrintDAO;
import zy.dto.money.access.AccessListDto;
import zy.entity.PageData;
import zy.entity.PageInfo;
import zy.entity.approve.T_Approve_Record;
import zy.entity.money.access.T_Money_Access;
import zy.entity.money.access.T_Money_AccessList;
import zy.entity.money.bank.T_Money_Bank;
import zy.entity.money.bank.T_Money_BankRun;
import zy.entity.sell.cashier.T_Sell_Cashier;
import zy.entity.sys.user.T_Sys_User;
import zy.service.money.access.AccessService;
import zy.util.CommonUtil;
import zy.util.DateUtil;
import zy.util.StringUtil;

@Service
public class AccessServiceImpl implements AccessService{
	@Resource
	private AccessDAO accessDAO;
	@Resource
	private ApproveRecordDAO approveRecordDAO;
	@Resource
	private BankDAO bankDAO;
	@Resource
	private BankRunDAO bankRunDAO;
	@Resource
	private PrintDAO printDAO;
	
	@Override
	public PageData<T_Money_Access> page(Map<String, Object> params) {
		Integer pageSize = (Integer)params.get(CommonUtil.PAGESIZE);
		Integer pageIndex = (Integer)params.get(CommonUtil.PAGEINDEX);
		
		Integer totalCount = accessDAO.count(params);
		PageInfo pageInfo = new PageInfo(totalCount, pageSize, pageIndex);
		params.put(CommonUtil.START, (pageIndex-1)*pageSize);
		params.put(CommonUtil.END, pageSize);
		
		List<T_Money_Access> list = accessDAO.list(params);
		PageData<T_Money_Access> pageData = new PageData<T_Money_Access>();
		pageData.setPageInfo(pageInfo);
		pageData.setList(list);
		return pageData;
	}

	@Override
	public T_Money_Access load(Integer ac_id) {
		T_Money_Access access = accessDAO.load(ac_id);
		if(access != null){
			T_Approve_Record approve_Record = approveRecordDAO.load(access.getAc_number(), access.getCompanyid());
			if(approve_Record != null){
				access.setAr_describe(approve_Record.getAr_describe());
			}
		}
		return access;
	}
	
	@Override
	public T_Money_Access load(String number,Integer companyid) {
		return accessDAO.load(number, companyid);
	}
	
	@Override
	public List<T_Money_AccessList> temp_list(Map<String, Object> params) {
		return accessDAO.temp_list(params);
	}

	@Override
	@Transactional
	public void temp_save(List<T_Money_AccessList> temps, T_Sys_User user) {
		if (temps == null || temps.size() == 0) {
			throw new RuntimeException("请选择银行账户");
		}
		List<String> existCode = accessDAO.temp_check(user.getUs_id(),user.getCompanyid());
		List<T_Money_AccessList> temps_add = new ArrayList<T_Money_AccessList>();
		for (T_Money_AccessList temp : temps) {
			if(!existCode.contains(temp.getAcl_ba_code())){
				temp.setAcl_us_id(user.getUs_id());
				temp.setAcl_remark("");
				temp.setAcl_type(0);
				temp.setCompanyid(user.getCompanyid());
				temps_add.add(temp);
			}
		}
		if (temps_add.size() > 0) {
			accessDAO.temp_save(temps_add);
		}
	}
	
	@Override
	@Transactional
	public void temp_save(List<T_Money_AccessList> temps, T_Sell_Cashier cashier) {
		if (temps == null || temps.size() == 0) {
			throw new RuntimeException("请选择银行账户");
		}
		List<String> existCode = accessDAO.temp_check_sell(cashier.getCa_id(), cashier.getCompanyid());
		List<T_Money_AccessList> temps_add = new ArrayList<T_Money_AccessList>();
		for (T_Money_AccessList temp : temps) {
			if(!existCode.contains(temp.getAcl_ba_code())){
				temp.setAcl_ca_id(cashier.getCa_id());
				temp.setAcl_remark("");
				temp.setAcl_type(0);
				temp.setCompanyid(cashier.getCompanyid());
				temps_add.add(temp);
			}
		}
		if (temps_add.size() > 0) {
			accessDAO.temp_save(temps_add);
		}
	}

	@Override
	@Transactional
	public void temp_updateMoney(T_Money_AccessList temp) {
		accessDAO.temp_updateMoney(temp);
	}
	
	@Override
	@Transactional
	public void temp_updateType(T_Money_AccessList temp) {
		accessDAO.temp_updateType(temp);
	}

	@Override
	@Transactional
	public void temp_updateRemark(T_Money_AccessList temp) {
		temp.setAcl_remark(StringUtil.decodeString(temp.getAcl_remark()));
		accessDAO.temp_updateRemark(temp);
	}

	@Override
	@Transactional
	public void temp_del(Integer acl_id) {
		accessDAO.temp_del(acl_id);
	}

	@Override
	@Transactional
	public void temp_clear(Map<String, Object> params) {
		accessDAO.temp_clear(params);
	}
	
	@Override
	public List<T_Money_AccessList> detail_list(Map<String, Object> params) {
		return accessDAO.detail_list(params);
	}
	
	@Override
	@Transactional
	public void save(T_Money_Access access, T_Sys_User user) {
		if(access == null){
			throw new IllegalArgumentException("参数不能为null");
		}
		if(StringUtil.isEmpty(access.getAc_manager())){
			throw new IllegalArgumentException("经办人不能为空");
		}
		access.setCompanyid(user.getCompanyid());
		access.setAc_us_id(user.getUs_id());
		access.setAc_maker(user.getUs_name());
		access.setAc_ar_state(CommonUtil.AR_STATE_NOTAPPROVE);
		access.setAc_sysdate(DateUtil.getCurrentTime());
		if(CommonUtil.ONE.equals(user.getShoptype()) || CommonUtil.TWO.equals(user.getShoptype())){//总公司、分公司
			access.setAc_shop_code(user.getUs_shop_code());
		}else{
			access.setAc_shop_code(user.getShop_upcode());
		}
		//1.查临时表
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("acl_us_id", user.getUs_id());
		params.put("companyid", user.getCompanyid());
		List<T_Money_AccessList> temps = accessDAO.temp_list(params);
		if(temps == null || temps.size() == 0){
			throw new RuntimeException("单据已保存，请勿重复提交");
		}
		//2.保存单据
		double ac_money = 0d;
		for (T_Money_AccessList temp : temps) {
			if(temp.getAcl_money().doubleValue() == 0d){
				throw new RuntimeException("明细数据存在为0的数据，请修改");
			}
			if(temp.getAcl_type().intValue() == 1){
				temp.setAcl_money(-Math.abs(temp.getAcl_money()));
			}
			ac_money += temp.getAcl_money();
		}
		access.setAc_money(ac_money);
		accessDAO.save(access, temps);
		//3.删除临时表
		accessDAO.temp_clear(params);
	}
	
	@Override
	@Transactional
	public void save(T_Money_Access access, T_Sell_Cashier cashier) {
		if(access == null){
			throw new IllegalArgumentException("参数不能为null");
		}
		access.setCompanyid(cashier.getCompanyid());
		access.setAc_ca_id(cashier.getCa_id());
		access.setAc_maker(cashier.getEm_name());
		access.setAc_manager(cashier.getEm_name());
		access.setAc_ar_state(CommonUtil.AR_STATE_NOTAPPROVE);
		access.setAc_sysdate(DateUtil.getCurrentTime());
		if(CommonUtil.FOUR.equals(cashier.getShop_type().toString())){//加盟店
			access.setAc_shop_code(cashier.getCa_shop_code());
		}else {
			access.setAc_shop_code(cashier.getShop_upcode());
		}
		//1.查临时表
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("acl_ca_id", cashier.getCa_id());
		params.put("companyid", cashier.getCompanyid());
		List<T_Money_AccessList> temps = accessDAO.temp_list(params);
		if(temps == null || temps.size() == 0){
			throw new RuntimeException("单据已保存，请勿重复提交");
		}
		//2.保存单据
		double ac_money = 0d;
		for (T_Money_AccessList temp : temps) {
			if(temp.getAcl_money().doubleValue() == 0d){
				throw new RuntimeException("明细数据存在为0的数据，请修改");
			}
			if(temp.getAcl_type().intValue() == 1){
				temp.setAcl_money(-Math.abs(temp.getAcl_money()));
			}
			ac_money += temp.getAcl_money();
		}
		access.setAc_money(ac_money);
		accessDAO.save(access, temps);
		//3.删除临时表
		accessDAO.temp_clear(params);
	}
	
	@Override
	@Transactional
	public void update(T_Money_Access access, T_Sys_User user) {
		if(access == null){
			throw new IllegalArgumentException("参数不能为null");
		}
		if(StringUtil.isEmpty(access.getAc_manager())){
			throw new IllegalArgumentException("经办人不能为空");
		}
		access.setCompanyid(user.getCompanyid());
		access.setAc_us_id(user.getUs_id());
		access.setAc_maker(user.getUs_name());
		access.setAc_ar_state(CommonUtil.AR_STATE_NOTAPPROVE);
		access.setAc_sysdate(DateUtil.getCurrentTime());
		//1.查临时表
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("acl_us_id", user.getUs_id());
		params.put("companyid", user.getCompanyid());
		List<T_Money_AccessList> temps = accessDAO.temp_list(params);
		if(temps == null || temps.size() == 0){
			throw new RuntimeException("单据已保存，请勿重复提交");
		}
		//1.2验证单据
		T_Money_Access oldAccess = accessDAO.check(access.getAc_number(), user.getCompanyid());
		if (oldAccess == null || !CommonUtil.AR_STATE_FAIL.equals(oldAccess.getAc_ar_state())) {
			throw new RuntimeException("单据已修改，请勿重复提交");
		}
		//2.保存单据
		double ac_money = 0d;
		for (T_Money_AccessList temp : temps) {
			if(temp.getAcl_money().doubleValue() == 0d){
				throw new RuntimeException("明细数据存在为0的数据，请修改");
			}
			if(temp.getAcl_type().intValue() == 1){
				temp.setAcl_money(-Math.abs(temp.getAcl_money()));
			}
			ac_money += temp.getAcl_money();
		}
		access.setAc_money(ac_money);
		accessDAO.deleteList(access.getAc_number(), user.getCompanyid());
		accessDAO.update(access, temps);
		//3.删除临时表
		accessDAO.temp_clear(params);
	}
	
	@Override
	@Transactional
	public void update(T_Money_Access access, T_Sell_Cashier cashier) {
		if(access == null){
			throw new IllegalArgumentException("参数不能为null");
		}
		access.setCompanyid(cashier.getCompanyid());
		access.setAc_ca_id(cashier.getCa_id());
		access.setAc_maker(cashier.getEm_name());
		access.setAc_manager(cashier.getEm_name());
		access.setAc_ar_state(CommonUtil.AR_STATE_NOTAPPROVE);
		access.setAc_sysdate(DateUtil.getCurrentTime());
		//1.查临时表
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("acl_ca_id", cashier.getCa_id());
		params.put("companyid", cashier.getCompanyid());
		List<T_Money_AccessList> temps = accessDAO.temp_list(params);
		if(temps == null || temps.size() == 0){
			throw new RuntimeException("单据已保存，请勿重复提交");
		}
		//1.2验证单据
		T_Money_Access oldAccess = accessDAO.check(access.getAc_number(), cashier.getCompanyid());
		if (oldAccess == null || !CommonUtil.AR_STATE_FAIL.equals(oldAccess.getAc_ar_state())) {
			throw new RuntimeException("单据已修改，请勿重复提交");
		}
		//2.保存单据
		double ac_money = 0d;
		for (T_Money_AccessList temp : temps) {
			if(temp.getAcl_money().doubleValue() == 0d){
				throw new RuntimeException("明细数据存在为0的数据，请修改");
			}
			if(temp.getAcl_type().intValue() == 1){
				temp.setAcl_money(-Math.abs(temp.getAcl_money()));
			}
			ac_money += temp.getAcl_money();
		}
		access.setAc_money(ac_money);
		accessDAO.deleteList(access.getAc_number(), cashier.getCompanyid());
		accessDAO.update(access, temps);
		//3.删除临时表
		accessDAO.temp_clear(params);
	}
	
	@Override
	@Transactional
	public T_Money_Access approve(String number, T_Approve_Record record, T_Sys_User user) {
		if (number == null) {
			throw new IllegalArgumentException("参数number不能为null");
		}
		T_Money_Access access = accessDAO.check(number, user.getCompanyid());
		if(access == null){
			throw new RuntimeException("单据不存在");
		}
		if(!CommonUtil.AR_STATE_NOTAPPROVE.equals(access.getAc_ar_state())){
			throw new RuntimeException("单据已经审核");
		}
		//更新单据审核状态
		access.setAc_ar_state(record.getAr_state());
		access.setAc_ar_date(DateUtil.getCurrentTime());
		accessDAO.updateApprove(access);
		//保存审核记录表
		record.setAr_number(number);
		record.setAr_sysdate(DateUtil.getCurrentTime());
		record.setAr_us_name(user.getUs_name());
		record.setAr_type("t_money_access");
		record.setCompanyid(user.getCompanyid());
		approveRecordDAO.save(record);
		if(!CommonUtil.AR_STATE_APPROVED.equals(access.getAc_ar_state())){//审核不通过，则直接返回
			return access;
		}
		//3.审核通过:银行账目及流水
		List<AccessListDto> details = accessDAO.listBank4Approve(number, user.getCompanyid());
		List<T_Money_Bank> banks = new ArrayList<T_Money_Bank>();
		List<T_Money_BankRun> bankRuns = new ArrayList<T_Money_BankRun>();
		for (AccessListDto dto : details) {
			dto.setBa_balance(dto.getBa_balance() + dto.getAcl_money());
			banks.add(dto);
			T_Money_BankRun bankRun = new T_Money_BankRun();
			bankRun.setBr_ba_code(dto.getBa_code());
			bankRun.setBr_balance(dto.getBa_balance());
			bankRun.setBr_bt_code(CommonUtil.BANKRUN_MONEY_ACCESS);
			bankRun.setBr_date(access.getAc_date());
			if(dto.getAcl_money()>0){
				bankRun.setBr_enter(Math.abs(dto.getAcl_money()));
			}else {
				bankRun.setBr_out(Math.abs(dto.getAcl_money()));
			}
			bankRun.setBr_manager(access.getAc_manager());
			bankRun.setBr_number(access.getAc_number());
			bankRun.setBr_remark(access.getAc_remark());
			bankRun.setBr_shop_code(dto.getBa_shop_code());
			bankRun.setBr_sysdate(DateUtil.getCurrentTime());
			bankRun.setCompanyid(user.getCompanyid());
			bankRuns.add(bankRun);
		}
		bankDAO.updateBalanceById(banks);
		bankRunDAO.save(bankRuns);
		return access;
	}
	
	@Override
	@Transactional
	public T_Money_Access reverse(String number, T_Sys_User user) {
		if (number == null) {
			throw new IllegalArgumentException("参数number不能为null");
		}
		T_Money_Access access = accessDAO.check(number, user.getCompanyid());
		if(access == null){
			throw new RuntimeException("单据不存在");
		}
		if(!CommonUtil.AR_STATE_APPROVED.equals(access.getAc_ar_state())){
			throw new RuntimeException("单据未审核或审核未通过");
		}
		//1.更新单据审核状态
		access.setAc_ar_state(CommonUtil.AR_STATE_NOTAPPROVE);
		access.setAc_ar_date(DateUtil.getCurrentTime());
		accessDAO.updateApprove(access);
		//2.保存审核记录表
		T_Approve_Record record = new T_Approve_Record();
		record.setAr_state(CommonUtil.AR_STATE_REVERSE_APPROVE);
		record.setAr_describe(user.getUs_name()+"反审核单据");
		record.setAr_number(number);
		record.setAr_sysdate(DateUtil.getCurrentTime());
		record.setAr_us_name(user.getUs_name());
		record.setAr_type("t_money_access");
		record.setCompanyid(user.getCompanyid());
		approveRecordDAO.save(record);
		//3.反审核:银行账目及流水
		List<AccessListDto> details = accessDAO.listBank4Approve(number, user.getCompanyid());
		List<T_Money_Bank> banks = new ArrayList<T_Money_Bank>();
		List<T_Money_BankRun> bankRuns = new ArrayList<T_Money_BankRun>();
		for (AccessListDto dto : details) {
			dto.setBa_balance(dto.getBa_balance() - dto.getAcl_money());
			banks.add(dto);
			T_Money_BankRun bankRun = new T_Money_BankRun();
			bankRun.setBr_ba_code(dto.getBa_code());
			bankRun.setBr_balance(dto.getBa_balance());
			bankRun.setBr_bt_code(CommonUtil.BANKRUN_MONEY_ACCESS);
			bankRun.setBr_date(access.getAc_date());
			if(dto.getAcl_money()>0){
				bankRun.setBr_out(Math.abs(dto.getAcl_money()));
			}else {
				bankRun.setBr_enter(Math.abs(dto.getAcl_money()));
			}
			bankRun.setBr_manager(access.getAc_manager());
			bankRun.setBr_number(access.getAc_number());
			bankRun.setBr_remark("反审核恢复账目");
			bankRun.setBr_shop_code(dto.getBa_shop_code());
			bankRun.setBr_sysdate(DateUtil.getCurrentTime());
			bankRun.setCompanyid(user.getCompanyid());
			bankRuns.add(bankRun);
		}
		bankDAO.updateBalanceById(banks);
		bankRunDAO.save(bankRuns);
		return access;
	}

	@Override
	@Transactional
	public void initUpdate(String number, Integer us_id, Integer companyid) {
		List<T_Money_AccessList> details = accessDAO.detail_list_forsavetemp(number, companyid);;
		for(T_Money_AccessList item:details){
			item.setAcl_us_id(us_id);
			if(item.getAcl_money()>0){
				item.setAcl_type(0);
			}else {
				item.setAcl_type(1);
			}
			item.setAcl_money(Math.abs(item.getAcl_money()));
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("acl_us_id", us_id);
		params.put("companyid", companyid);
		accessDAO.temp_clear(params);
		accessDAO.temp_save(details);
	}
	
	@Override
	@Transactional
	public void initUpdate_Sell(String number, Integer ca_id, Integer companyid) {
		List<T_Money_AccessList> details = accessDAO.detail_list_forsavetemp(number, companyid);;
		for(T_Money_AccessList item:details){
			item.setAcl_ca_id(ca_id);
			if(item.getAcl_money()>0){
				item.setAcl_type(0);
			}else {
				item.setAcl_type(1);
			}
			item.setAcl_money(Math.abs(item.getAcl_money()));
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("acl_ca_id", ca_id);
		params.put("companyid", companyid);
		accessDAO.temp_clear(params);
		accessDAO.temp_save(details);
	}
	
	@Override
	@Transactional
	public void del(String number, Integer companyid) {
		if (number == null) {
			throw new IllegalArgumentException("参数number不能为null");
		}
		T_Money_Access access = accessDAO.check(number, companyid);
		if(access == null){
			throw new RuntimeException("单据不存在");
		}
		if(!CommonUtil.AR_STATE_NOTAPPROVE.equals(access.getAc_ar_state()) && !CommonUtil.AR_STATE_FAIL.equals(access.getAc_ar_state())){
			throw new RuntimeException("单据已审核通过不能删除！");
		}
		accessDAO.del(number, companyid);
	}
	
	@Override
	public Map<String, Object> loadPrintData(String number, Integer sp_id, T_Sys_User user) {
		Map<String, Object> resultMap = printDAO.loadPrint4Bill(sp_id);
		T_Money_Access access = accessDAO.load(number, user.getCompanyid());
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("acl_number", number);
		params.put("companyid", user.getCompanyid());
		List<T_Money_AccessList> accessList = accessDAO.detail_list(params);
		resultMap.put("access", access);
		resultMap.put("accessList", accessList);
		return resultMap;
	}
	
}
